'use strict';
var util = require('../util/index')
var formatRes = util.formatRes
var uuid = require('node-uuid')
var https = require('https')
var unzipResponse = require('unzip-response')
class RpcClient {
  constructor(token, config) {
    this.token = token
    this.key = config.getKey()
    this.secret = config.getSecret()
    this.apiAddress = config.getApiAddress()
    this.apiOptions = {
      method: 'POST',
      host: this.apiAddress,
      path: '/api/v1/',
      headers: {
        'Content-type': "application/json;charset=utf-8",
        'Accept-Encoding': 'gzip',
        'User-Agent': 'eleme-openapi-nodejs-sdk'
      }
    }
    this.log = config.log
  }

  request(action, params) {
    let postData = this.getPostData(action, params);
    return new Promise((resolve, reject) => {
      this.post(this.apiOptions, postData)
        .then(resText => {
          var resJson = JSON.parse(resText);
          if (!resJson.error) {
            resolve(resJson.result)
          } else {
            reject(resJson.error)
          }
        })
    })
  }

  requestForUser(action, params) {
    let postData = this.getPostData(action, params);
    return new Promise((resolve, reject) => {
      this.post(this.apiOptions, postData)
        .then(resText => {
          var resJson = util.formatRes(resText);
          if (!resJson.error) {
            resolve(resJson.result)
          } else {
            reject(resJson.error)
          }
        })
    })
  }

  post(options, postData) {
    if (this.log) {
      this.log.info(postData)
    }
    return new Promise(function(resolve, reject) {
      var req = https.request(options, function(res) {
        res = unzipResponse(res)
        res.setEncoding('utf8');
        var json = ''
        res.on('data', function (chunk) {
          json += chunk;
        });
        res.on('end', function() {
          if (this.log) {
            this.log.info(json)
          }
          resolve(json)
        })
      })
      req.on('error', function (e) {
        console.log('problem with request: ' + e.message);
        if (this.log) {
          this.log.error(postData)
        }
        reject(e)
      })
      req.write(postData);
      req.end();
    })
  }

  getPostData(action, params) {
    var timestamp = parseInt(new Date().getTime()/1000)
    let reqId = this.getReqId()
    console.log("request Id: " + reqId)
    let options = {
      token: this.token,
      nop: "1.0.0",
      metas: {
        app_key: this.key,
        timestamp: timestamp,
      },
      params: params || {},
      action: action,
      id: reqId,
      signature: this.getSignature(timestamp, action, params)
    }
    return JSON.stringify(options)
  }

  getReqId () {
    var timestamp = new Date().getTime()
    return uuid.v4().split('-').join('').toUpperCase() + '|' + String(timestamp)
  }

  getSignature (timestamp, action, params) {
    var crypto = require('crypto');
    let obj = {
      'app_key': this.key,
      'timestamp': timestamp
    }
    for (let key in params) {
      obj[key] = params[key]
    }

    // 构造kv数组
    let arr = []
    for (let key in obj) {
      let kv = String(key) + '=' + JSON.stringify(obj[key])
      arr.push(kv)
    }

    // array按首字母排序
    arr.sort()
    //  action + token + arr.join() + secret
    var str = action + this.token + arr.join('') + this.secret;
    // to md5
    var md5 = crypto.createHash('md5');
    md5.update(str);
    return md5.digest('hex').toUpperCase()
  }
}

module.exports = RpcClient;